package com.taxigang.server;

import java.util.Collection;
import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import com.allen_sauer.gwt.log.client.Log;
import com.taxigang.shared.AwardInfo;
import com.taxigang.shared.LoginInfo;
import com.taxigang.shared.TaxiGangInfo;
import com.taxigang.shared.TaxiGanguserInfo;
import com.taxigang.shared.TaxiGanguserInfo.Status;

public class TaxiGangUserDAO {
	ExceptionHandler exceptionHandler = new ExceptionHandler();
	private EntityManager em;
	public TaxiGangUserDAO(EntityManager em){
		this.em = em;
	}

	synchronized public boolean add(TaxiGanguser user) {
		boolean result = true;
		try{
			EntityTransaction transaction = em.getTransaction();
			transaction.begin();
			em.persist(user); 
			transaction.commit();
		} catch (Exception ex){
			exceptionHandler.add(ex);
			result = false;
		} finally {
			//em.close();
		}
		return result;
	}

	//* Next  add the code to TaxiGanguserController to remove a record

	synchronized public boolean remove(TaxiGanguser user) {
		try{
			EntityTransaction transaction = em.getTransaction();
			transaction.begin();
			TaxiGanguser userx = em.find(TaxiGanguser.class, user.getId());
			em.remove(userx); 
			transaction.commit();
		} catch (Exception ex){
			exceptionHandler.add(ex);
		} finally {
			//em.close();
			return false;
		}
	}

	//	//* Finally add the code to TaxiGanguserController to update a record
	//
	//	synchronized public boolean updateAddressHistory(TaxiGanguserInfo userInfo, TaxiGangInfo taxiGangInfo) {
	//		EntityManager em = getEntityManager();
	//		try{
	//			EntityTransaction transaction = em.getTransaction();
	//			transaction.begin();
	//			TaxiGanguser userx = get (userInfo.getId());
	//			userx.updateAddressHistory(taxiGangInfo); 
	//
	//			//other fields
	//			transaction.commit();
	//		} catch (Exception ex){
	//			exceptionHandler.add(ex);
	//		} finally {
	//			//em.close();
	//			return false;
	//		}
	//	}

	//* Finally add the code to TaxiGanguserController to update a record

	//	public boolean update(TaxiGanguser user) {
	//		EntityManager em = getEntityManager();
	//		try{
	//			EntityTransaction transaction = em.getTransaction();
	//			transaction.begin();
	//			TaxiGanguser userx = em.find(TaxiGanguser.class, user.getId());
	//
	//			userx.setDisplayname(user.getDisplayname()) ;
	//			userx.mergeCityHistory(user.getCityList()); 
	//			userx.mergeAddressHistory(user.getAddressList()); 
	//
	//			//other fields
	//			transaction.commit();
	//
	//		} catch (Exception ex){
	//			exceptionHandler.add(ex);
	//		}
	//		finally {
	//			//em.close();
	//		}
	//		return true;
	//	}

	//	public TaxiGanguser get(LoginInfo loginInfo){
	//		Log.info("TaxiGangUserDAO:get"+loginInfo.getId());
	//		TaxiGanguser taxiganguser;
	//		EntityTransaction transaction = em.getTransaction();
	//		if (loginInfo.getIsTempory()){
	//			Query query = em.createNamedQuery("TaxiGanguser.findByTemporaryUsername");
	//			query.setParameter("temporaryusername", loginInfo.getTemporyUserName());
	//			try {
	//				transaction.begin();
	//				taxiganguser = (TaxiGanguser)query.getSingleResult();
	//				if (taxiganguser.getTemporaryPassword().equals(loginInfo.getTemporyPassword())){
	//					taxiganguser.setStatus(Status.OK);				
	//				} else {
	//					taxiganguser.setStatus(Status.USERNAME_INUSE);								
	//				}
	//
	//			} catch (NoResultException ex){
	//				taxiganguser = new TaxiGanguser(loginInfo);
	//				em.persist(taxiganguser);
	//				taxiganguser.setStatus(Status.OK);
	//			} finally {
	//				transaction.commit();				
	//			}
	//
	//		} else {
	//			try {
	//				transaction.begin();
	//				Query query = em.createNamedQuery("TaxiGanguser.findById");
	//				query.setParameter("id", loginInfo.getId());
	//				taxiganguser = (TaxiGanguser)query.getSingleResult();
	//			} catch (NoResultException ex){
	//				taxiganguser = new TaxiGanguser(loginInfo);
	//				em.persist(taxiganguser);
	//			} finally {
	//				transaction.commit();				
	//			}
	//		}
	//		taxiganguser.setDisplayname(loginInfo.getNickname());
	//		return taxiganguser;
	//	}

	//	public Key getKey(String id){
	//		Key key = null;
	//		Query query = em.createNamedQuery("TaxiGanguser.findById");
	//		query.setParameter("id", id);
	//		try {
	//			TaxiGanguser taxiganguser = (TaxiGanguser)query.getSingleResult();
	//			key = taxiganguser.getKey();
	//		}catch (NoResultException ex){
	//			throw new RuntimeException();
	//		} finally {
	//			//
	//		}
	//		return key;
	//	}

	public void addToMyTaxiGangs(String taxiGanguserId, long taxiGangId){
		//add the leader to my taxigangs
		em.getTransaction().begin();
		TaxiGanguser user = get(taxiGanguserId);
		int s = user.getMyTaxiGangs().size();

		user.addTaxigang(taxiGangId);
		em.persist(user);
		em.getTransaction().commit();
	}

	public void removeFromMyTaxiGangs(String taxiGanguserId, long taxiGangId){
		//add the leader to my taxigangs
		em.getTransaction().begin();
		TaxiGanguser user = get(taxiGanguserId);
		int s = user.getMyTaxiGangs().size();
		user.removeTaxigang(taxiGangId);
		s = user.getMyTaxiGangs().size();

		em.persist(user);
		em.getTransaction().commit();
	}

	synchronized public TaxiGanguserInfo getInfo(LoginInfo loginInfo){
		Log.info("**TaxiGangUserDAO:get id="+loginInfo.getId());
		TaxiGanguserInfo taxiGanguserInfo = null;
		TaxiGanguser taxiganguser = null;
		EntityTransaction transaction = em.getTransaction();
		Log.info("TaxiGangUserDAO:getInfo transaction id="+transaction.hashCode());
		if (loginInfo.getIsTempory()){
			Query query = em.createNamedQuery("TaxiGanguser.findByTemporaryUsername");
			query.setParameter("temporaryusername", loginInfo.getTemporyUserName());
			try {
				taxiganguser = (TaxiGanguser)query.getSingleResult();
				if (taxiganguser.getTemporaryPassword().equals(loginInfo.getTemporyPassword())){
					taxiganguser.setStatus(Status.OK);				
				} else {
					taxiganguser.setStatus(Status.USERNAME_INUSE);								
				}

			} catch (NoResultException ex){
				transaction.begin();
				taxiganguser = new TaxiGanguser(loginInfo);
				em.persist(taxiganguser);
				taxiganguser.setStatus(Status.OK);
			} finally {
				taxiganguser.setDisplayname(loginInfo.getNickname());
				taxiGanguserInfo = taxiganguser.getInfo();
				transaction.commit();				
			}

		} else {
			try {
				Log.info("TaxiGangDAO:getInfo permanent id="+loginInfo.getId());
				Query query = em.createNamedQuery("TaxiGanguser.findById");
				query.setParameter("id", loginInfo.getId());
				taxiganguser = (TaxiGanguser)query.getSingleResult();
				taxiGanguserInfo = taxiganguser.getInfo();
			} catch (NoResultException ex){
				Log.info("TaxiGangDAO:getInfo no result");
				transaction.begin();
				taxiganguser = new TaxiGanguser(loginInfo);
				String nickName = loginInfo.getNickname();
				taxiganguser.setDisplayname(nickName);
				em.persist(taxiganguser);
				taxiGanguserInfo = taxiganguser.getInfo();
				transaction.commit();				
			} catch (Exception ex){
				Log.error("TaxiGangDAO:getInfo "+ex.getMessage());
			} finally {
			}
		}
		return taxiGanguserInfo;
	}


	synchronized public void deleteAll(){
		EntityTransaction transaction = em.getTransaction();
		try{
			Query query = em.createNamedQuery("TaxiGanguser.findAll");
			Collection<TaxiGanguser> taxigangusers = query.getResultList();
			for (TaxiGanguser taxiGanguser : taxigangusers){
				transaction.begin();
				em.remove(taxiGanguser);
				transaction.commit();
			}
		} catch (Exception ex){
			exceptionHandler.add(ex);
		}
	}

	public TaxiGanguser get(String id) {
		Query query = em.createNamedQuery("TaxiGanguser.findById");
		query.setParameter("id", id);
		TaxiGanguser taxiganguser;
		try {
			taxiganguser = (TaxiGanguser)query.getSingleResult();
		} catch (NoResultException ex){
			taxiganguser = null;
		} catch (Exception ex){
			taxiganguser = null;
			throw new RuntimeException(ex);
		}

		return  taxiganguser;
	}

	public TaxiGangInfo getMembers(TaxiGangInfo info, long thisUserId) {

		if (!"CLOSED".equals(info.getStatus())){
			TaxiGanguserInfo[]memberInfos = new TaxiGanguserInfo[info.getNumMembers()];
			int i=0;
			for (Long useId : info.getMemberIds()){
				TaxiGanguser user = em.find(TaxiGanguser.class, useId);
				memberInfos[i++]=user.getInfo();
			}
			info.setMembers(memberInfos);
		}else{
			TaxiGanguserInfo[]awardingmembers = new TaxiGanguserInfo[info.getNumMembers()-1];

			int i=0;
			for (Long useId : info.getMemberIds()){
				TaxiGanguser user = em.find(TaxiGanguser.class, useId);
				if (thisUserId!=useId){
					awardingmembers[i++]=user.getInfo();
				}
			}
			info.setMembers(awardingmembers);
			
			boolean show = false;
			for (TaxiGanguserInfo taxiganginfo :awardingmembers){
				if (taxiganginfo != null){
					show = true;
					break;
				}
			}
			if (!show){
				info.setStatus("DONT_SHOW");
			}

		}
		return info;
	}

	public void award(TaxiGangInfo taxiganginfo,String userId, TaxiGangDAO taxiGangDAO) {
		EntityTransaction transaction = em.getTransaction();
		int i=0;
		for (TaxiGanguserInfo taxiGanguserInfo : taxiganginfo.getMember()){
			boolean isLeader = i==0;
			transaction.begin();
			TaxiGanguser user = get(taxiGanguserInfo.getId());
			AwardInfo awarded = taxiGanguserInfo.getAwarded();
			awarded.setDate(new Date());
			if (isLeader){
				awarded.addBonus(isLeader);
			}
			user.award(new Award(awarded));
			em.persist(user);
			transaction.commit();
			i++;
		}

		//now set taxigang awarding user
		TaxiGanguser taxiGanguser = get(userId);
		taxiGangDAO.updateAwardingUser(taxiganginfo, taxiGanguser);
	}
}
